#ifndef HASH_H
#define HASH_H

#include <stdbool.h>
#include <stddef.h>

/* *****************************************************************
 *                DEFINICION DE LOS TIPOS DE DATOS
 * *****************************************************************/

typedef struct hash hash_t;
typedef struct hash_iter hash_iter_t;
typedef void (*hash_destruir_dato_t)(void *);

/* *****************************************************************
 *                    PRIMITIVAS DEL HASH
 * *****************************************************************/
			 /*Primitivas básicas*/
// Crea una hash.
// Post: devuelve un nuevo hash vacío.
hash_t *hash_crear(hash_destruir_dato_t destruir_dato);

// Guarda un nuevo elemento en el hash (clave y valor) si es que la clave no existe 
// en el hash, de existir modifica el valor que tenia relacionado. 
// Pre: El hash fue creado.
// Post: Devuelve un booleano segun si se pudo o no guardar el elemento.
bool hash_guardar(hash_t *hash, const char *clave, void *dato);

// Borra el elemento del hash, si es que este pertenecia al hash, de no existir 
// el elemento de dicha calve devuelve NULL
// Pre: El hash fue creado.
// Post: Devuelve el valor relacionado a la clave que se borro del hash o NULL en caso de 
// que no exista la clave en el hash.
void *hash_borrar(hash_t *hash, const char *clave);

// Devuelve el valor almacenado junto con la clave que recibe en caso de que esta pertenesca
// a los elementos del hash.
// Pre: El hash fue creado.
// Post: Devuelve el valor relacionado a la clave, en caso de que exista sino devuelve NULL
void *hash_obtener(const hash_t *hash, const char *clave);

// Devuelve un booleano verdadero en caso de que la clave se encuntre almacenada en el hash
// y falso en caso contrario.
// Pre: El hash fue creado
// Post: Devuelve un boleano segun se encuentre o no la clave
bool hash_pertenece(const hash_t *hash, const char *clave);

// Devuelve la cantidad de elemetos que posee el hash.
// Pre: el hash fue creado.
size_t hash_cantidad(const hash_t *hash);

// Destruye el hash. Si el hash tiene la función destruir_dato por parámetro,
// para cada uno de los valores de los elementos del hash llama a destruir_dato.
// Pre: el hash fue creado. destruir_dato es una función capaz de destruir
// los valores de los elementos del hash, o NULL en caso de que no se la utilice.
// Post: se eliminaron todos los elementos del hash y este se destruye.
void hash_destruir(hash_t *hash);


			 /*Primitivas de iteración*/
		
// Crea un iterador de hash.
// Pre: El hash fue creado. 
// Post: devuelve un iterador, apuntando a primer elemento del hash en caso que lo haya,
// de lo contrario el iterador queda al final del hash.		 
hash_iter_t *hash_iter_crear(const hash_t *hash);

// Avanza el iterador al siguiente elemento del hash. En caso de error devuelve false.
// Pre: el iterador y el hash fueron creados.
// Post: devuelve un booleano si pudo o no avanzar el iterador.
bool hash_iter_avanzar(hash_iter_t *iter);

// Devuelve el dato al que esta apuntando el iterador. Si el iterador esta en el final del arbol
// devuelve NULL.
// Pre: el iterador y el arbol fueron creados.
// Post: Devuelve la clave a la que apuntaba el iterador o NULL.
const char *hash_iter_ver_actual(const hash_iter_t *iter);

// Devuelve true o false si el iterador se encuantra al final o no del hash.
// Pre: el iterador y el fueron creados.
// Post: devuelve un booleano segun donde apunte el iterador.
bool hash_iter_al_final(const hash_iter_t *iter);

// Destruye el iterador.
// Pre: el iterador fue creado.
void hash_iter_destruir(hash_iter_t* iter);

#endif // HASH_H
			 

